package app.ui;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;

import common.MessageHandle;
import common.MessageHandle.MessageType;
import common.User;

public class ChatScr extends AbsCommonPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4676095861535175693L;

	protected JTextArea jTextArea; // display message
	protected JTextArea jTextArea2; // type message
	protected JScrollPane jScrollPane; // hold displaying message
	protected JScrollPane jScrollPane2; // hold typing message
	protected JButton jButton; // send
	protected JTable jTable; // Show who's online
	protected DefaultTableModel tableModel;
	protected final String[] btnLables = { "Send", "Connect" };

	private ObjectInputStream ois;
	private ObjectOutputStream oos;
	private Object obj;
	private MessageHandle message, userMessage;
	private int targetClientID = 0;
	private String userName = "User";
	private User user = null; // Point to me

	public ChatScr(MainFrame mFrame) {
		super(mFrame);
	}

	@Override
	protected void addComponents() {
		this.jTextArea = new JTextArea();
		this.jTextArea2 = new JTextArea();
		this.jScrollPane = new JScrollPane(jTextArea);
		this.jScrollPane2 = new JScrollPane(jTextArea2);
		this.jButton = new JButton(btnLables[1]);
		this.jTable = new JTable();

		add(jScrollPane);
		add(jScrollPane2);
		add(jButton);
		add(jTable);
	}

	@Override
	protected void initializeComponents() {
		// jTextArea
		jTextArea.setEditable(false);
		jTextArea.getInsets().left = 5;
		jTextArea.setWrapStyleWord(true);
		jTextArea.setLineWrap(true);
		// jTable
		jTable.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		tableModel = new DefaultTableModel(new Object[] { "Online users" }, 0);
		jTable.setModel(tableModel);
		jTable.setAutoscrolls(true);

		// jTextArea2
		jTextArea2.setLineWrap(true);
		jTextArea2.setWrapStyleWord(true);
		jTextArea.getInsets().left = 5;
		// jScrollPane
		jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		// jScrollPane2
		jScrollPane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		// jButton
		jButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				String btnText = jButton.getText();

				if (btnText.equals(btnLables[0])) {
					// Do SEND
					try {
						doSendAMessage(jTextArea2.getText());
					} catch (IOException e1) {
						// e1.printStackTrace();
						doDisplayText("Server does not respond...");
					}
				}
				else if (btnText.equals(btnLables[1])) {
					// Do CONNECT
					Thread t = new Thread(new Runnable() {
						public void run() {
							try {
								doConnectToServer();
							} catch (IOException e) {
								// e.printStackTrace();
								jButton.setText(btnLables[1]);
								doDisplayText("Server is down!");
								doDisplayText("Click connect button to reconnect to server");
							}
						}
					});

					t.start();

					// Change the button label
					jButton.setText(btnLables[0]);
				}
			}
		});
	}

	@Override
	protected void resizeComponents() {
		int x = btnWid / 3;
		int y = btnHei / 2;
		int width = this.getWidth() - 2 * x;
		int height = this.getHeight() * 3 / 4 - y;

		// jScrollPane
		width = this.getWidth() - 2 * x - btnWid + 4;
		jScrollPane.setBounds(x, y, width, height);
		jScrollPane.updateUI();

		// jTable
		x += width + 4;
		width = btnWid;
		jTable.setBounds(x, y, width, height);

		// jScrollPane2
		x = btnWid / 3;
		y += height + btnHei / 2;
		height = this.getHeight() / 4 - btnHei;
		width = this.getWidth() - 2 * x - btnWid + 4;
		jScrollPane2.setBounds(x, y, width, height);
		jScrollPane2.updateUI();

		// jButton
		x += width + 4;
		width = btnWid;
		jButton.setBounds(x, y, width, height);
	}

	protected synchronized void doDisplayText(String text) {
		if (text != null) {
			if (message != null) {
				text = message.getOwner() + ":  " + text;

				// Delete current object
				message = null;
			}
			String str = this.getjTextArea().getText() + "\n" + text;
			this.getjTextArea().setText(str);
		}
		else if (message != null) {
			String str = message.getMessage();
			switch (message.getMsType()) {
			case SYSTEM:
				// TODO list out online users
				int i = tableModel.getRowCount();
				while (i > 0) {
					tableModel.removeRow(--i);
				}

				ArrayList<User> lstOln = message.getListOnline();
				Object[] objs = new Object[1];
				for (User u : lstOln) {
					if (user == null && u.getUserID() == Integer.valueOf(str)) {
						user = u;
					}

					if (u != user) {
						objs[0] = u;
						tableModel.addRow(objs);
					}
				}
				break;
			default:
				doDisplayText(str);
				break;
			}
		}
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	protected synchronized void doConnectToServer() throws IOException {
		Socket socket = null;

		try {
			socket = new Socket("localhost", 4444);
			oos = new ObjectOutputStream(socket.getOutputStream());
			ois = new ObjectInputStream(socket.getInputStream());
		} catch (UnknownHostException e) {
			System.err.println("Connect Failed to server 4444!");
			System.exit(1);
		}

		// Initialize message handler and send a message contain user's properties
		userMessage = new MessageHandle(userName);
		userMessage.setMsType(MessageType.SYSTEM);
		doSendAMessage(null);

		// Wait for a message from server and print out
		try {
			while (!socket.isInputShutdown() && (obj = ois.readObject()) != null) {
				message = (MessageHandle) obj;
				doDisplayText(null);
			}
		} catch (ClassNotFoundException e) {
			// e.printStackTrace();
			System.err.println("SERVER IS SHUTDOWN!"); // server is shutdown.
		}

		oos.close();
		ois.close();
		socket.close();
	}

	protected void doSendAMessage(String text) throws IOException {
		if (text != null && text.trim().length() > 0) {
			userMessage = new MessageHandle(userName);
			userMessage.setTargetClientID(getTargetClientID());
			userMessage.setMessage(text);

			int rIdx = jTable.getSelectedRow();
			if (rIdx > -1) {
				User u = (User) tableModel.getValueAt(rIdx, 0);
				userMessage.setTargetClientID(u.getUserID());
				userMessage.setMsType(MessageType.PRIVATE);
			}
		} else if (userMessage == null) {
			return;
		}

		oos.writeObject(userMessage);
		oos.flush();

		userMessage = null;
		// Clear the text box
		jTextArea2.setText("");
	}

	public JTextArea getjTextArea() {
		return jTextArea;
	}

	public JTextArea getjTextArea2() {
		return jTextArea2;
	}

	public JScrollPane getjScrollPane() {
		return jScrollPane;
	}

	public JScrollPane getjScrollPane2() {
		return jScrollPane2;
	}

	public JButton getjButton() {
		return jButton;
	}

	public String[] getBtnLables() {
		return btnLables;
	}

	public int getTargetClientID() {
		return targetClientID;
	}

	public void setTargetClientID(int targetClientID) {
		this.targetClientID = targetClientID;
	}

}
